package com.example.opengldemo.util;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.List;

public final class ShapeFactory {


    public static float[] getCubeArrayData(float side) {
        float UNIT_SIZE = 0.2f;
        if (side > 0) {
            UNIT_SIZE = side;
        }
        return new float[]
                {
                        0, 0, UNIT_SIZE,
                        UNIT_SIZE, UNIT_SIZE, UNIT_SIZE,
                        -UNIT_SIZE, UNIT_SIZE, UNIT_SIZE,
                        0, 0, UNIT_SIZE,
                        -UNIT_SIZE, UNIT_SIZE, UNIT_SIZE,
                        -UNIT_SIZE, -UNIT_SIZE, UNIT_SIZE,
                        0, 0, UNIT_SIZE,
                        -UNIT_SIZE, -UNIT_SIZE, UNIT_SIZE,
                        UNIT_SIZE, -UNIT_SIZE, UNIT_SIZE,
                        0, 0, UNIT_SIZE,
                        UNIT_SIZE, -UNIT_SIZE, UNIT_SIZE,
                        UNIT_SIZE, UNIT_SIZE, UNIT_SIZE,

                        0, 0, -UNIT_SIZE,
                        UNIT_SIZE, UNIT_SIZE, -UNIT_SIZE,
                        UNIT_SIZE, -UNIT_SIZE, -UNIT_SIZE,
                        0, 0, -UNIT_SIZE,
                        UNIT_SIZE, -UNIT_SIZE, -UNIT_SIZE,
                        -UNIT_SIZE, -UNIT_SIZE, -UNIT_SIZE,
                        0, 0, -UNIT_SIZE,
                        -UNIT_SIZE, -UNIT_SIZE, -UNIT_SIZE,
                        -UNIT_SIZE, UNIT_SIZE, -UNIT_SIZE,
                        0, 0, -UNIT_SIZE,
                        -UNIT_SIZE, UNIT_SIZE, -UNIT_SIZE,
                        UNIT_SIZE, UNIT_SIZE, -UNIT_SIZE,

                        -UNIT_SIZE, 0, 0,
                        -UNIT_SIZE, UNIT_SIZE, UNIT_SIZE,
                        -UNIT_SIZE, UNIT_SIZE, -UNIT_SIZE,
                        -UNIT_SIZE, 0, 0,
                        -UNIT_SIZE, UNIT_SIZE, -UNIT_SIZE,
                        -UNIT_SIZE, -UNIT_SIZE, -UNIT_SIZE,
                        -UNIT_SIZE, 0, 0,
                        -UNIT_SIZE, -UNIT_SIZE, -UNIT_SIZE,
                        -UNIT_SIZE, -UNIT_SIZE, UNIT_SIZE,
                        -UNIT_SIZE, 0, 0,
                        -UNIT_SIZE, -UNIT_SIZE, UNIT_SIZE,
                        -UNIT_SIZE, UNIT_SIZE, UNIT_SIZE,

                        UNIT_SIZE, 0, 0,
                        UNIT_SIZE, UNIT_SIZE, UNIT_SIZE,
                        UNIT_SIZE, -UNIT_SIZE, UNIT_SIZE,
                        UNIT_SIZE, 0, 0,
                        UNIT_SIZE, -UNIT_SIZE, UNIT_SIZE,
                        UNIT_SIZE, -UNIT_SIZE, -UNIT_SIZE,
                        UNIT_SIZE, 0, 0,
                        UNIT_SIZE, -UNIT_SIZE, -UNIT_SIZE,
                        UNIT_SIZE, UNIT_SIZE, -UNIT_SIZE,
                        UNIT_SIZE, 0, 0,
                        UNIT_SIZE, UNIT_SIZE, -UNIT_SIZE,
                        UNIT_SIZE, UNIT_SIZE, UNIT_SIZE,

                        0, UNIT_SIZE, 0,
                        UNIT_SIZE, UNIT_SIZE, UNIT_SIZE,
                        UNIT_SIZE, UNIT_SIZE, -UNIT_SIZE,
                        0, UNIT_SIZE, 0,
                        UNIT_SIZE, UNIT_SIZE, -UNIT_SIZE,
                        -UNIT_SIZE, UNIT_SIZE, -UNIT_SIZE,
                        0, UNIT_SIZE, 0,
                        -UNIT_SIZE, UNIT_SIZE, -UNIT_SIZE,
                        -UNIT_SIZE, UNIT_SIZE, UNIT_SIZE,
                        0, UNIT_SIZE, 0,
                        -UNIT_SIZE, UNIT_SIZE, UNIT_SIZE,
                        UNIT_SIZE, UNIT_SIZE, UNIT_SIZE,

                        0, -UNIT_SIZE, 0,
                        UNIT_SIZE, -UNIT_SIZE, UNIT_SIZE,
                        -UNIT_SIZE, -UNIT_SIZE, UNIT_SIZE,
                        0, -UNIT_SIZE, 0,
                        -UNIT_SIZE, -UNIT_SIZE, UNIT_SIZE,
                        -UNIT_SIZE, -UNIT_SIZE, -UNIT_SIZE,
                        0, -UNIT_SIZE, 0,
                        -UNIT_SIZE, -UNIT_SIZE, -UNIT_SIZE,
                        UNIT_SIZE, -UNIT_SIZE, -UNIT_SIZE,
                        0, -UNIT_SIZE, 0,
                        UNIT_SIZE, -UNIT_SIZE, -UNIT_SIZE,
                        UNIT_SIZE, -UNIT_SIZE, UNIT_SIZE,
                };
    }

    public float[] getCubeNormalArray() {
        return new float[]{
                0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1,//前面上6个顶点的法向量
                0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1,//后面上6个顶点的法向量
                -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0,//左面上6个顶点的法向量
                1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, //右面上 6 个顶点的法向量
                0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, //上面上 6 个顶点的法向量
                0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, //下面上6个顶点的法向量
        };
    }

    public static float[] getBallArrayData(float r, int span) {
        ArrayList<Float> alVertix = new ArrayList<Float>();
        final int angleSpan = span;
        for (int vAngle = -90; vAngle < 90; vAngle = vAngle + angleSpan) {

            for (int hAngle = 0; hAngle <= 360; hAngle = hAngle + angleSpan) {
                float x0 = (float) (r * Math.cos(Math.toRadians(vAngle)) * Math.cos(Math.toRadians(hAngle)));
                float y0 = (float) (r * Math.cos(Math.toRadians(vAngle)) * Math.sin(Math.toRadians(hAngle)));
                float z0 = (float) (r * Math.sin(Math.toRadians(vAngle)));

                float x1 = (float) (r * Math.cos(Math.toRadians(vAngle))
                        * Math.cos(Math.toRadians(hAngle + angleSpan)));

                float y1 = (float) (r * Math.cos(Math.toRadians(vAngle))
                        * Math.sin(Math.toRadians(hAngle + angleSpan)));
                float z1 = (float) (r * Math.sin(Math.toRadians(vAngle)));

                float x2 = (float) (r * Math.cos(Math.toRadians(vAngle + angleSpan)) * Math.cos(Math.toRadians(hAngle + angleSpan)));

                float y2 = (float) (r * Math.cos(Math.toRadians(vAngle + angleSpan)) * Math.sin(Math.toRadians(hAngle + angleSpan)));

                float z2 = (float) (r * Math.sin(Math.toRadians(vAngle + angleSpan)));

                float x3 = (float) (r * Math.cos(Math.toRadians(vAngle +
                        angleSpan)) * Math.cos(Math.toRadians(hAngle)));

                float y3 = (float) (r * Math.cos(Math.toRadians(vAngle + angleSpan))
                        * Math.sin(Math.toRadians(hAngle)));

                float z3 = (float) (r * Math.sin(Math.toRadians(vAngle + angleSpan)));

                alVertix.add(x1);
                alVertix.add(y1);
                alVertix.add(z1);
                alVertix.add(x3);
                alVertix.add(y3);
                alVertix.add(z3);
                alVertix.add(x0);
                alVertix.add(y0);
                alVertix.add(z0);
                alVertix.add(x1);
                alVertix.add(y1);
                alVertix.add(z1);
                alVertix.add(x2);
                alVertix.add(y2);
                alVertix.add(z2);
                alVertix.add(x3);
                alVertix.add(y3);
                alVertix.add(z3);

            }
        }

        int vCount = alVertix.size() / 3;
        float vertices[] = new float[vCount * 3];

        for (int i = 0; i < alVertix.size(); i++) {
            vertices[i] = alVertix.get(i);
        }
        return vertices;
    }

    public static float[] getTriangleArray() {
        final float UNIT_SIZE = 0.2f;
        return new float[]{
                -4 * UNIT_SIZE, 0, 0,
                0, -4 * UNIT_SIZE, 0,
                +4 * UNIT_SIZE, 0, 0
        };
    }

    public static float[] getRectangleArray() {
        final float UNIT_SIZE = 0.2f;
        return new float[]{
                -4 * UNIT_SIZE, 4 * UNIT_SIZE, 0,
                4 * UNIT_SIZE, 4 * UNIT_SIZE, 0,
                4 * UNIT_SIZE, -4 * UNIT_SIZE, 0,
                -4 * UNIT_SIZE, -4 * UNIT_SIZE, 0
        };
    }

    public static float[] getHexagon(float R, float r) {
        List<Float> flist = new ArrayList<Float>();
        float tempAngle = 360 / 6;
        for (float angle = 0; angle < 360; angle += tempAngle) {
            flist.add(0f);
            flist.add(0f);
            flist.add(0f);
            flist.add((float) (R * Math.cos(Math.toRadians(angle))));
            flist.add((float) (R * Math.sin(Math.toRadians(angle))));
            flist.add(0f);
            flist.add((float) (r * Math.cos(Math.toRadians(angle
                    + tempAngle / 2))));
            flist.add((float) (r * Math.sin(Math.toRadians(angle
                    + tempAngle / 2))));
            flist.add(0f);
            flist.add(0f);
            flist.add(0f);
            flist.add(0f);
            flist.add((float) (r * Math.cos(Math.toRadians(angle
                    + tempAngle / 2))));
            flist.add((float) (r * Math.sin(Math.toRadians(angle
                    + tempAngle / 2))));
            flist.add(0f);
            flist.add((float) (R * Math.cos(Math.toRadians(angle
                    + tempAngle))));
            flist.add((float) (R * Math.sin(Math.toRadians(angle
                    + tempAngle))));
            flist.add(0f);

        }
        int vCount = flist.size() / 3;
        float[] vertexArray = new float[flist.size()]; //顶点坐标数组
        for (int i = 0; i < vCount; i++) {
            vertexArray[i * 3] = flist.get(i * 3);
            vertexArray[i * 3 + 1] = flist.get(i * 3 + 1);
            vertexArray[i * 3 + 2] = flist.get(i * 3 + 2);
        }
        return vertexArray;
    }

    public static float[] getEarthgenerateTexCoor(int d) {
        int bw = 360 / d ;
        int bh = 180 / d ;
        float[] result = new float[bw * bh * 6 * 2];
        float sizew = 1.0f / bw;
        float sizeh = 1.0f / bh;
        int c = 0;
        for (int i = 0; i < bh; i++) {
            for (int j = 0; j < bw; j++) {
                float s = j * sizew;
                float t = i * sizeh;
                result[c++] = s;
                result[c++] = t;  // 左上角
                result[c++] = s;
                result[c++] = t + sizeh; //左下
                result[c++] = s + sizew;
                result[c++] = t;        // 右上
                result[c++] = s + sizew;
                result[c++] = t;   //右上
                result[c++] = s;
                result[c++] = t + sizeh; //左下
                result[c++] = s + sizew;
                result[c++] = t + sizeh; //右下
            }
        }
        return result;
    }


    public static FloatBuffer getFloatBuffer(float[] array) {
        return (FloatBuffer) ByteBuffer.allocateDirect(array.length * 4)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(array)
                .position(0);
    }

    public static float[] getEarthVertexArray(float r , int angleSpan){

        ArrayList<Float> alVertix=new ArrayList<Float>();
        //vAngle>-90
        for(float vAngle=90;vAngle>-90;vAngle=vAngle-angleSpan){
            for(float hAngle=360;hAngle>0;hAngle=hAngle-angleSpan){
                double xozLength=r*Math.cos(Math.toRadians(vAngle));
                float x1=(float)(xozLength*Math.cos(Math.toRadians(hAngle)));
                float z1=(float)(xozLength*Math.sin(Math.toRadians(hAngle)));
                float y1=(float)(r*Math.sin(Math.toRadians(vAngle)));
                xozLength=r*Math.cos(Math.toRadians(vAngle-angleSpan));
                float x2=(float)(xozLength*Math.cos(Math.toRadians(hAngle)));
                float z2=(float)(xozLength*Math.sin(Math.toRadians(hAngle)));
                float y2=(float)(r*Math.sin(Math.toRadians(vAngle-angleSpan)));
                xozLength=r*Math.cos(Math.toRadians(vAngle-angleSpan));
                float x3=(float)(xozLength*Math.cos(Math.toRadians(hAngle-angleSpan)));
                float z3=(float)(xozLength*Math.sin(Math.toRadians(hAngle-angleSpan)));
                float y3=(float)(r*Math.sin(Math.toRadians(vAngle-angleSpan)));
                xozLength=r*Math.cos(Math.toRadians(vAngle));
                float x4=(float)(xozLength*Math.cos(Math.toRadians(hAngle-angleSpan)));
                float z4=(float)(xozLength*Math.sin(Math.toRadians(hAngle-angleSpan)));
                float y4=(float)(r*Math.sin(Math.toRadians(vAngle)));

                alVertix.add(x1);alVertix.add(y1);alVertix.add(z1);
                alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
                alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);

                alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);
                alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
                alVertix.add(x3);alVertix.add(y3);alVertix.add(z3);
            }}
        int vCount=alVertix.size()/3;
        float vertices[]=new float[vCount*3];
        for(int i=0;i<alVertix.size();i++){
            vertices[i]=alVertix.get(i);
        }
        return vertices ;
    }


    public static float[] getFragDataArray(int vCount) {
        float[] colorArray = new float[vCount * 4];//顶点着色数据的初始化
        for (int i = 0; i < vCount; i++) {
            if (i % 3 == 0) { //中心点为白色，RGBA 4 个通道[1,1,1,0]
                colorArray[i * 4] = 1;
                colorArray[i * 4 + 1] = 1;
                colorArray[i * 4 + 2] = 1;
                colorArray[i * 4 + 3] = 0;
            } else { //边上的点为淡蓝色，RGBA 4 个通道[0.45,0.75,0.75,0]
                colorArray[i * 4] = 0.45f;
                colorArray[i * 4 + 1] = 0.75f;
                colorArray[i * 4 + 2] = 0.75f;
                colorArray[i * 4 + 3] = 0;
            }
        }
        return colorArray;
    }


    public static float[] getBallVertexArray(float r , int angleSpan){

        ArrayList<Float> alVertix=new ArrayList<Float>();
        //vAngle>-90
        for(float vAngle=90;vAngle>-90;vAngle=vAngle-angleSpan){
            for(float hAngle=360;hAngle>0;hAngle=hAngle-angleSpan){
                double xozLength=r*Math.cos(Math.toRadians(vAngle));
                float x1=(float)(xozLength*Math.cos(Math.toRadians(hAngle)));
                float z1=(float)(xozLength*Math.sin(Math.toRadians(hAngle)));
                float y1=(float)(r*Math.sin(Math.toRadians(vAngle)));
                xozLength=r*Math.cos(Math.toRadians(vAngle-angleSpan));
                float x2=(float)(xozLength*Math.cos(Math.toRadians(hAngle)));
                float z2=(float)(xozLength*Math.sin(Math.toRadians(hAngle)));
                float y2=(float)(r*Math.sin(Math.toRadians(vAngle-angleSpan)));
                xozLength=r*Math.cos(Math.toRadians(vAngle-angleSpan));
                float x3=(float)(xozLength*Math.cos(Math.toRadians(hAngle-angleSpan)));
                float z3=(float)(xozLength*Math.sin(Math.toRadians(hAngle-angleSpan)));
                float y3=(float)(r*Math.sin(Math.toRadians(vAngle-angleSpan)));
                xozLength=r*Math.cos(Math.toRadians(vAngle));
                float x4=(float)(xozLength*Math.cos(Math.toRadians(hAngle-angleSpan)));
                float z4=(float)(xozLength*Math.sin(Math.toRadians(hAngle-angleSpan)));
                float y4=(float)(r*Math.sin(Math.toRadians(vAngle)));

                alVertix.add(x1);alVertix.add(y1);alVertix.add(z1);
                alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
                alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);

                alVertix.add(x4);alVertix.add(y4);alVertix.add(z4);
                alVertix.add(x2);alVertix.add(y2);alVertix.add(z2);
                alVertix.add(x3);alVertix.add(y3);alVertix.add(z3);
            }}
        int vCount=alVertix.size()/3;
        float vertices[]=new float[vCount*3];
        for(int i=0;i<alVertix.size();i++){
            vertices[i]=alVertix.get(i);
        }
        return vertices ;
    }

    public static float[] getBallTexcoorsArray(int d) {
        int bw = 360 / d ;
        int bh = 180 / d ;
        float[] result = new float[bw * bh * 6 * 2];
        float sizew = 1.0f / bw;
        float sizeh = 1.0f / bh;
        int c = 0;
        for (int i = 0; i < bh; i++) {
            for (int j = 0; j < bw; j++) {
                float s = j * sizew;
                float t = i * sizeh;
                result[c++] = s;
                result[c++] = t;  // 左上角
                result[c++] = s;
                result[c++] = t + sizeh; //左下
                result[c++] = s + sizew;
                result[c++] = t;        // 右上
                result[c++] = s + sizew;
                result[c++] = t;   //右上
                result[c++] = s;
                result[c++] = t + sizeh; //左下
                result[c++] = s + sizew;
                result[c++] = t + sizeh; //右下
            }
        }
        return result;
    }
}
